import {
    PayableOverrides,
    BigNumber ,
    BigNumberish,
    Overrides,
    CallOverrides,
    Signer,
    providers
} from 'ethers';
import { IArrtibuteFactoryClient } from './IArrtibuteFactoryClient';
import { ArrtibuteAssertFactory ,ArrtibuteAssertFactory__factory } from "../../types";

export class EtherArrtibuteFactoryClient implements IArrtibuteFactoryClient {
    public arrtibuteAssertFactory: ArrtibuteAssertFactory | undefined;//typechain 合约
    public provider: providers.Provider | undefined;
    public signer: Signer | undefined;
    public _waitConfirmations = 5;

    public connectProvider(address: string, provider: providers.Provider): void{
        this.provider = provider;
        this.arrtibuteAssertFactory = ArrtibuteAssertFactory__factory.connect(address,this.provider);
    }

    public connectSigner(signer: Signer): void{
        this.signer = signer;
    }

    public setWaitConfirmations(num: number): void{
        this._waitConfirmations = num;
    }

    public contract(): Promise<ArrtibuteAssertFactory> {
        if (this.provider === undefined || this.arrtibuteAssertFactory === undefined) {
          return Promise.reject('need to connect a valid provider');
        }
        return Promise.resolve(this.arrtibuteAssertFactory);
    }

    public async NewArrtibuteAssert(
        _artwork_name: string,
        _artwork_image_uri: string,
        _artwork_metadata_uri: string,
        total_issue_num: BigNumberish,
        name: string,
        symbol: string,
        config?: Overrides & { from?: string | Promise<string> }
    ): Promise<any>{
      if (
        this.provider === undefined ||
        this.arrtibuteAssertFactory === undefined ||
        this.signer === undefined
      ){
          return Promise.reject('need to connect a valid provider and signer');
      }

      const gas = await this.arrtibuteAssertFactory
      .connect(this.signer)
      .estimateGas.NewArrtibuteAssert(_artwork_name,_artwork_image_uri,_artwork_metadata_uri,total_issue_num,name,symbol ,{...config});


      const transaction = await this.arrtibuteAssertFactory
      .connect(this.signer)
      .NewArrtibuteAssert(_artwork_name,_artwork_image_uri,_artwork_metadata_uri,total_issue_num,name,symbol,{ gasLimit: gas.mul(13).div(10), ...config });
      
      const receipt = await transaction.wait(this._waitConfirmations);
      return receipt
    }
  
    public   getArtistIssue(
      _artist: string,
      config?: CallOverrides
    ): Promise<BigNumber[]>{
      if (
          this.provider === undefined ||
          this.arrtibuteAssertFactory === undefined 
      ){
          return Promise.reject('need to connect a valid provider');
      }

      return this.arrtibuteAssertFactory.getArtistIssue(_artist,{...config});

    }
  
    public getAssertByIndex(
      index: BigNumberish,
      config?: CallOverrides
    ): Promise<{ _assert: string; _assertIndex: BigNumber }>
    {
      if (
          this.provider === undefined ||
          this.arrtibuteAssertFactory === undefined 
      ){
          return Promise.reject('need to connect a valid provider');
      }
      return this.arrtibuteAssertFactory.getAssertByIndex(index,{...config});
    }
  
    public getAsserts(
      config?: CallOverrides
    ): Promise<
      ({ _assert: string; _assertIndex: BigNumber })[]
    >{
      if (
        this.provider === undefined ||
        this.arrtibuteAssertFactory === undefined 
      ){
          return Promise.reject('need to connect a valid provider');
      }
      return this.arrtibuteAssertFactory.getAsserts({...config});
    }
  
    public getTraitType(
      config?: CallOverrides
    ): Promise<number>{
      if (
        this.provider === undefined ||
        this.arrtibuteAssertFactory === undefined 
      ){
          return Promise.reject('need to connect a valid provider');
      }
      return this.arrtibuteAssertFactory.getTraitType({...config});
    }
  
    public owner(config?: CallOverrides): Promise<string>{
      if (
        this.provider === undefined ||
        this.arrtibuteAssertFactory === undefined 
      ){
          return Promise.reject('need to connect a valid provider');
      }
      return this.arrtibuteAssertFactory.owner({...config});
    }
  
}
